#pragma once

#include "Audio/Tests/Test.Application.h"

#undef  APP_NAME
#define APP_NAME	TestSlesAudio
#undef  APP_BASE
#define APP_BASE	TestApp


using namespace android;

#define USE_AUDIO_ENGINE

#ifdef USE_AUDIO_ENGINE
#	define USE_AUDIO_SAMPLE
#endif


class APP_NAME : public APP_BASE
{
private:
#	ifndef USE_AUDIO_ENGINE
	SLObjectItf		_engineObject	;
	SLEngineItf		_engine			;
	SLObjectItf		_outputMix		;
#	endif

#	ifdef USE_AUDIO_SAMPLE
	AudioSamplePtr		sample;

#	else

	SLObjectItf		_playerObject	;
	SLPlayItf		_playerPlay		;
	SLSeekItf		_playerSeek		;
	SLmillisecond	_duration		;
	SLVolumeItf		_volumeObj;
#	endif
		


public:
	APP_NAME (IPlatform *platform, EDevice::type deviceType) :
		APP_BASE( platform, deviceType )
	{
#	ifndef USE_AUDIO_ENGINE
		_engineObject	= null;
		_engine			= null;
		_outputMix		= null;
#	endif
		
#	ifndef USE_AUDIO_SAMPLE
		_playerObject	= null;
		_playerPlay		= null;
		_playerSeek		= null;
		_volumeObj		= null;
		_duration		= 0;
#	endif
	}
		
	void Update (float dt) override
	{
		APP_BASE::Update( dt );

	}

	void OnEnter () override
	{
		APP_BASE::OnEnter();

		//SLObjectItf		tmp_engine = (SLObjectItf) 0x2c2cf8;
		//(*tmp_engine)->Destroy( tmp_engine );


#	ifndef USE_AUDIO_ENGINE
		// engine
		SL_CALL( slCreateEngine( &_engineObject, 0, null, 0, null, null ) );
		CHECK_ERR( _engineObject != null, );

		SL_CALL( (*_engineObject)->Realize( _engineObject, SL_BOOLEAN_FALSE ) );
		SL_CALL( (*_engineObject)->GetInterface( _engineObject, SL_IID_ENGINE, &_engine ) );
		CHECK_ERR( _engine != null, );
	
		// output mix
		{
		const SLInterfaceID	ids[1] = {SL_IID_ENVIRONMENTALREVERB};
		const SLboolean		req[1] = {SL_BOOLEAN_FALSE};
		SL_CALL( (*_engine)->CreateOutputMix( _engine, &_outputMix, /*1, ids, req*/ 0, null, null ) );
		CHECK_ERR( _outputMix != null, );

		SL_CALL( (*_outputMix)->Realize( _outputMix, SL_BOOLEAN_FALSE ) );
		}
#	else

		SLEngineItf		_engine	= ESS()->GetAudioEngine()->GetAPI();
		SLObjectItf		_outputMix = ESS()->GetAudioEngine()->GetOutputMix();
		CHECK_ERR( _engine != null, );
		CHECK_ERR( _outputMix != null, );
#	endif

		AAssetManager *	am		= Platforms::AndroidPlatform::GetInstance()->GetJavaInterface()->GetAssetManager();
		CHECK_ERR( am != null, );

		AAsset *		asset	= AAssetManager_open( am, "sound/mk.mp3", AASSET_MODE_UNKNOWN );
		CHECK_ERR( asset != null, );
		
		long	start,
				length;
		int		fd		= AAsset_openFileDescriptor( asset, &start, &length );
		
		AAsset_close( asset );
		CHECK_ERR( fd >= 0, );
		DEBUG_CONSOLE( (string("file desc: ") << fd ).cstr() );

		SLDataLocator_AndroidFD	loc_fd		= { SL_DATALOCATOR_ANDROIDFD, fd, start, length };
		SLDataFormat_MIME		format_mime	= { SL_DATAFORMAT_MIME, null, SL_CONTAINERTYPE_UNSPECIFIED };
		SLDataSource			audio_src	= { &loc_fd, &format_mime };

		SLDataLocator_OutputMix	loc_outmix	= { SL_DATALOCATOR_OUTPUTMIX, _outputMix };
		SLDataSink				audio_sink	= { &loc_outmix, null };


#	ifdef USE_AUDIO_SAMPLE

		sample = AudioSample::New( ESS() );

		CHECK_ERR( sample->_Create( &audio_src, &audio_sink ), );

		sample->SetLooping( true );
		sample->Play();

#	else
		{
		const SLInterfaceID	ids[]	= { SL_IID_SEEK, SL_IID_VOLUME };
		const SLboolean		req[]	= { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
		STATIC_ASSERTE( COUNT_OF( ids ) == COUNT_OF( req ) );
		
		SL_CALL( (*_engine)->CreateAudioPlayer( _engine, &_playerObject, &audio_src,
									&audio_sink, CountOf(ids), ids, req ) );
		}

		CHECK_ERR( _playerObject != null, );
		SL_CALL( (*_playerObject)->Realize( _playerObject, SL_BOOLEAN_FALSE ) );
		
		// get interfaces
		SL_CALL( (*_playerObject)->GetInterface( _playerObject, SL_IID_PLAY,	&_playerPlay ) );
		CHECK_ERR( _playerPlay != null, );

		SL_CALL( (*_playerObject)->GetInterface( _playerObject, SL_IID_SEEK,	&_playerSeek ) );
		CHECK_ERR( _playerSeek != null, );
		
		SL_CALL( (*_playerPlay)->GetDuration( _playerPlay, &_duration ) );

		if ( _duration != SL_TIME_UNKNOWN )
			DEBUG_CONSOLE( (string("duration: ") << (_duration * 0.001f) ).cstr() );
		
		SL_CALL( (*_playerObject)->GetInterface( _playerObject, SL_IID_VOLUME,	&_volumeObj ) );
		CHECK_ERR( _volumeObj != null, );
		
		SLmillibel volume = SL_MILLIBEL_MIN;
		SL_CALL( (*_volumeObj)->GetMaxVolumeLevel( _volumeObj, &volume ) );
		DEBUG_CONSOLE( (string("max volume: ") << volume).cstr() );

		//SL_CALL( (*_volumeObj)->SetVolumeLevel( _volumeObj, SL_MILLIBEL_MIN / 8 ) );

		SL_CALL( (*_volumeObj)->GetVolumeLevel( _volumeObj, &volume ) );
		DEBUG_CONSOLE( (string("volume: ") << volume ).cstr() );

		SL_CALL( (*_playerSeek)->SetLoop( _playerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN ) );
		
		SL_CALL( (*_playerPlay)->SetPlayState( _playerPlay, SL_PLAYSTATE_PLAYING ) );
#	endif
	}
	
	void OnExit () override
	{

#	ifndef USE_AUDIO_SAMPLE
		if ( _playerObject != null )
		{
			(*_playerObject)->Destroy( _playerObject );
			_playerObject = null;
		}
#	endif

#	ifndef USE_AUDIO_ENGINE
		if ( _outputMix != null )
		{
			(*_outputMix)->Destroy( _outputMix );
			_outputMix	= null;
		}

		if ( _engineObject != null )
		{
			(*_engineObject)->Destroy( _engineObject );
			_engineObject	= null;
			_engine			= null;
		}
#	endif

		APP_BASE::OnExit();
	}
};
